/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.icee.myth.server;

import com.icee.myth.common.message.dbMessage.DBMessage;
import com.icee.myth.common.message.dbMessage.DBMessage.DBMessageType;
import com.icee.myth.common.message.dbMessage.SimpleDBMessage;
import com.icee.myth.common.messageQueue.DBMessageQueue;
import com.icee.myth.common.messageQueue.ServerMessageQueue;
import com.icee.myth.server.dbHandler.MapDBHandler;
import com.icee.myth.server.message.dbMessage.CreateCharDBMessage;
import com.icee.myth.server.message.dbMessage.GetBriefPlayerInfosDBMessage;
import com.icee.myth.server.message.dbMessage.GetCharDetailDBMessage;
import com.icee.myth.server.message.dbMessage.GetCharNumDBMessage;
import com.icee.myth.server.message.dbMessage.GetRelationDBMessage;
import com.icee.myth.server.message.dbMessage.SaveCharInfoDBMessage;
import com.icee.myth.server.message.dbMessage.SaveRelationDBMessage;
import com.icee.myth.server.message.dbMessage.AddNormalActivityDBMessage;
import com.icee.myth.server.message.dbMessage.ChangePlayerNameDBMessage;
import com.icee.myth.server.message.dbMessage.DeleteNormalActivityDBMessage;
import com.icee.myth.server.message.dbMessage.GetCouponDBMessage;
import com.icee.myth.server.message.dbMessage.GetNewMailDBMessage;
import com.icee.myth.server.message.dbMessage.SaveBillDBMessage;
import com.icee.myth.server.message.dbMessage.SaveMailDBMessage;
import com.icee.myth.server.message.serverMessage.builder.MapMessageBuilder;
import com.icee.myth.utils.Consts;
import com.icee.myth.utils.LinkedTransferQueue;
import com.icee.myth.log.GameLogger;
import com.icee.myth.log.message.FileDebugGameLogMessage;
import com.icee.myth.log.message.builder.GameLogMessageBuilder;
import com.icee.myth.server.message.dbMessage.ConsumerLogDBMessage;
import com.icee.myth.server.message.dbMessage.GetCharOccupyInfoDBMessage;
import com.icee.myth.server.message.dbMessage.SaveCharOccupyInfoDBMessage;
import com.icee.myth.utils.StackTraceUtil;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

/**
 *
 * @author liuxianke
 */
public class DBThreadHandle implements Runnable {
    // 数据库操作的消息队列。DBMessageQueue.queue()：存放所有的数据库消息队列。
    protected final LinkedTransferQueue<DBMessage> messageQueue = DBMessageQueue.queue();
    protected Connection connection;
    private int keepAliveInterval;
    private boolean isDBDown = false;
    private boolean isShuttingDown = false;

    public DBThreadHandle(Connection connection) {
        this.connection = connection;
        keepAliveInterval = Consts.DB_KEEPALIVE_INTERVAL;
    }

    @Override
    public void run() {
        while (true) {
            // 处理消息队列中的消息
            handleMessages();

            if (isShuttingDown) {
                break;
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        StackTraceUtil.getStackTrace(ex)));
            }

            if (keepAliveInterval <= 0) {
                dbKeepAlive();
                keepAliveInterval = Consts.DB_KEEPALIVE_INTERVAL;
            } else {
                keepAliveInterval -= 100;
            }
        }
    }

    private void dbKeepAlive() {
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            stmt.executeQuery(Consts.DB_KEEPALIVE_TEST_STATEMENT);
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                    FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_INFO,
                    "DB Keep Alive Success."));
        } catch (SQLException ex) {
            GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDBErrorGameLogMessage(StackTraceUtil.getStackTrace(ex)));
        } finally {
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException ex) {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDBErrorGameLogMessage(StackTraceUtil.getStackTrace(ex)));
                }
            }
        }
    }

    protected void handleMessages() {
        // TODO: handle message from message queue
        SimpleDBMessage msg = (SimpleDBMessage) messageQueue.poll();
        while (msg != null) {
            boolean needSendShutdown = false;
            DBMessageType type = msg.getType();
            switch (type) {
                case GET_CHAR_NUM: {
                    GetCharNumDBMessage getCharNumDBMessage = (GetCharNumDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetCharNum(connection, getCharNumDBMessage.playerId);
                    }
                    break;
                }
                case CREATE_CHAR: {
                    CreateCharDBMessage createCharDBMessage = (CreateCharDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleCreateChar(connection, createCharDBMessage.playerId, createCharDBMessage.createCharInfo);
                    }
                    break;
                }
                case GET_CHAR_DETAIL: {
                    GetCharDetailDBMessage getCharDetailDBMessage = (GetCharDetailDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetCharDetail(connection, getCharDetailDBMessage.playerId);
                    }
                    break;
                }
                case SAVE_CHAR_INFO: {
                    SaveCharInfoDBMessage saveCharInfoDBMessage = (SaveCharInfoDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleUpdateCharDetailInfo(connection, saveCharInfoDBMessage.playerId, saveCharInfoDBMessage.charDetailInfo);
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildSaveCharInfoDBDownCacheGameLogMessage(saveCharInfoDBMessage));
                    }
                    break;
                }
                case GET_CHAR_OCCUPY_INFO: {
                    GetCharOccupyInfoDBMessage getCharOccupyInfoDBMessage = (GetCharOccupyInfoDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetCharOccupyInfo(connection, getCharOccupyInfoDBMessage.playerId);
                    }
                    break;
                }
                case SAVE_CHAR_OCCUPY_INFO: {
                    SaveCharOccupyInfoDBMessage saveCharOccupyInfoDBMessage = (SaveCharOccupyInfoDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleUpdateCharOccupyInfo(connection, saveCharOccupyInfoDBMessage.playerId, saveCharOccupyInfoDBMessage.occupyInfoProto);
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildSaveCharOccupyInfoDBDownCacheGameLogMessage(saveCharOccupyInfoDBMessage));
                    }
                    break;
                }
                case CHANGE_NAME: {
                    ChangePlayerNameDBMessage changePlayerNameDBMessage = (ChangePlayerNameDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleChangePlayerName(connection, changePlayerNameDBMessage.playerId, changePlayerNameDBMessage.newName);
                    }
                    break;
                }
                case ADD_NORMALACTIVITY: {
                    AddNormalActivityDBMessage addNormalActivityDBMessage = (AddNormalActivityDBMessage) msg;
                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleAddNormalActivity(connection, addNormalActivityDBMessage);
                    }
                    break;
                }
                case DELETE_NORMALACTIVITY: {
                    DeleteNormalActivityDBMessage deleteNormalActivityDBMessage = (DeleteNormalActivityDBMessage) msg;
                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleDeleteNormalActivity(connection, deleteNormalActivityDBMessage);
                    }
                    break;
                }
                case SAVE_RELATION: {
                    SaveRelationDBMessage saveRelationDBMessage = (SaveRelationDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleSaveRelation(connection, saveRelationDBMessage.playerId, saveRelationDBMessage.relationProto);
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildSaveRelationDBDownCacheGameLogMessage(saveRelationDBMessage));
                    }
                    break;
                }
                case GET_RELATION: {
                    GetRelationDBMessage getRelationDBMessage = (GetRelationDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetRelation(connection, getRelationDBMessage.playerId);
                    }
                    break;
                }
                case GET_BRIEF_PLAYER_INFOS: {
                    GetBriefPlayerInfosDBMessage getBriefPlayerInfosDBMessage = (GetBriefPlayerInfosDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetBriefPlayerInfos(connection, getBriefPlayerInfosDBMessage.playerId, getBriefPlayerInfosDBMessage.unknownFriends);
                    }
                    break;
                }
                case SAVE_BILL: {
                    SaveBillDBMessage saveBillDBMessage = (SaveBillDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleSaveBill(connection, saveBillDBMessage.playerId, saveBillDBMessage.passport, saveBillDBMessage.order.currencyId, (int) saveBillDBMessage.order.amount, saveBillDBMessage.order.memo, saveBillDBMessage.order.no, saveBillDBMessage.status, saveBillDBMessage.step);
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildSaveBillDBDownCacheGameLogMessage(saveBillDBMessage));
                    }
                    break;
                }
                case CONSUMER_LOG: {
                    ConsumerLogDBMessage consumerLogDBMessage = (ConsumerLogDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleSaveConsumerLog(connection, consumerLogDBMessage.playerId, consumerLogDBMessage.consumerType,
                                consumerLogDBMessage.goldNum, consumerLogDBMessage.goldType, consumerLogDBMessage.productId, consumerLogDBMessage.productNum);
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildSaveConsumerLogDBDownCacheGameLogMessage(consumerLogDBMessage));
                    }

                    break;
                }
                case GET_COUPON: {  // 注意：这个向数据库写入玩家成功领取coupon的消息
                    GetCouponDBMessage getCouponDBMessage = (GetCouponDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetcoupon(connection, getCouponDBMessage.playerId, getCouponDBMessage.passport, getCouponDBMessage.code, GameServer.INSTANCE.getCurrentTime());
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildGetCouponDBDownCacheGameLogMessage(getCouponDBMessage));
                    }
                    break;
                }
                case SAVE_MAIL: {
                    SaveMailDBMessage saveMailDBMessage = (SaveMailDBMessage) msg;

                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleSaveMail(connection,
                                                                                           saveMailDBMessage.mailId,
                                                                                           saveMailDBMessage.targetId,
                                                                                           saveMailDBMessage.title,
                                                                                           saveMailDBMessage.description,
                                                                                           saveMailDBMessage.rewardInfo,
                                                                                           GameServer.INSTANCE.getCurrentTime());
                    }

                    if (isDBDown) {
                        // 写到文件中，以便恢复数据
                        GameLogger.getlogger().log(GameLogMessageBuilder.buildSaveMailDBDownCacheGameLogMessage(saveMailDBMessage));
                    }
                    break;
                }
                case GET_NEW_MAIL: {
                    GetNewMailDBMessage getNewMailDBMessage = (GetNewMailDBMessage) msg;
                    
                    if (!isDBDown) {
                        needSendShutdown = isDBDown = !MapDBHandler.handleGetNewMail(connection, getNewMailDBMessage.playerId, getNewMailDBMessage.lastGlobalMaxMailId);
                    }

                    break;
                }
                case SHUTDOWN: {
                    isShuttingDown = true;
                    return;
                }
                default: {
                    GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                            FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                            "DB thread handle unknown message[" + type + "]."));
                    break;
                }
            }

            if (needSendShutdown) {
                // 记录关服日志（由于数据库断连）
                GameLogger.getlogger().log(GameLogMessageBuilder.buildFileDebugGameLogMessage(
                        FileDebugGameLogMessage.DebugLogType.DEBUGLOGTYPE_ERROR,
                        "Server shutdown because DB disconnected."));

                // 向主逻辑消息队列发关服命令
                ServerMessageQueue.queue().offer(MapMessageBuilder.buildShutdownMessage());
                needSendShutdown = false;
            }

            msg = (SimpleDBMessage) messageQueue.poll();
        }
    }
}
